package cn.guetzjb.security.utils;

import cn.guetzjb.core.constant.CacheConstants;
import cn.guetzjb.core.exception.auth.NotPermissionException;
import cn.guetzjb.core.exception.auth.NotRoleException;
import cn.guetzjb.core.utils.JwtUtils;
import cn.guetzjb.core.utils.SpringUtils;
import cn.guetzjb.redis.service.RedisService;
import cn.guetzjb.security.anotation.Logical;
import cn.guetzjb.security.anotation.RequiresPermissions;
import cn.guetzjb.security.anotation.RequiresRoles;
import cn.guetzjb.sys.domain.SysRole;
import cn.guetzjb.sys.model.LoginUser;
import com.alibaba.nacos.common.utils.StringUtils;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;

import java.util.Arrays;
import java.util.Set;

@UtilityClass
@Slf4j
public class AuthUtil {

    private final RedisService redisService = SpringUtils.getBean(RedisService.class);

    public LoginUser getLoginUser(String token) {
        LoginUser loginUser = null;
        try {
            if (!StringUtils.isEmpty(token)) {
                Long userId = JwtUtils.getUserId(token);
                loginUser = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + userId);
                return loginUser;
            }
        } catch (Exception e) {
            log.error("获取用户身份异常->{}", e.getMessage());
        }
        return null;
    }

    /**
     * @param requiresPermissions 权限注解
     * @return 是否具备该权限
     */
    public void checkPermission(RequiresPermissions requiresPermissions) {
        if (requiresPermissions.logical() == Logical.AND) {
            checkPermissionAnd(requiresPermissions);
        } else {
            checkPermissionOr(requiresPermissions);
        }
    }

    public void checkPermissionAnd(RequiresPermissions requiresPermissions) {
        Set<String> permissions = SecurityUtils.getLoginUser().getPermissions();
        if (permissions.contains("*")) {
            return;
        }
        for (String needPerm : requiresPermissions.value()) {
            if (!permissions.contains(needPerm)) {
                throw new NotPermissionException(StringUtils.join(Arrays.stream(requiresPermissions.value()).toList(), ","));
            }
        }
    }

    public void checkPermissionOr(RequiresPermissions requiresPermissions) {
        Set<String> permissions = SecurityUtils.getLoginUser().getPermissions();
        if (permissions.contains("*")) {
            return;
        }
        boolean ok = false;
        for (String needPerm : requiresPermissions.value()) {
            if (permissions.contains(needPerm)) {
                ok = true;
                break;
            }
        }
        if (!ok) {
            throw new NotPermissionException(StringUtils.join(Arrays.stream(requiresPermissions.value()).toList(), ","));
        }
    }

    public static void checkRole(RequiresRoles requiresRoles) {
        if (requiresRoles.logical() == Logical.AND) {
            checkRoleAnd(requiresRoles);
        } else {
            checkRoleOr(requiresRoles);
        }

    }

    private static void checkRoleOr(RequiresRoles requiresRoles) {
        Set<String> roles = SecurityUtils.getLoginUser().getRoles();
        boolean ok = false;
        for (String needRole : requiresRoles.value()) {
            if (roles.contains(needRole)) {
                ok = true;
                break;
            }
        }
        if (!ok) {
            throw new NotRoleException(StringUtils.join(Arrays.stream(requiresRoles.value()).toList(), ","));
        }
    }

    private static void checkRoleAnd(RequiresRoles requiresRoles) {
        Set<String> roles = SecurityUtils.getLoginUser().getRoles();
        for (String needRole : requiresRoles.value()) {
            if (!roles.contains(needRole)) {
                throw new NotRoleException(StringUtils.join(Arrays.stream(requiresRoles.value()).toList(), ","));
            }
        }
    }

    public static boolean isAdmin(Long userId){
        return userId == 1L;
    }

}
